﻿using DongFangGuoKai.WMS.IApiService;
using DongFangGuoKai.WMS.IApiService.ElectronicTags;
using DongFangGuoKai.WMSPlatform.Core.Repository;
using DongFangGuoKai.WMSPlatform.Domain.HZJLYModel;
using DongFangGuoKai.WMSPlatform.Domain.Models;
using DongFangGuoKai.WMSPlatform.Service.InboundOrderDetail.DTO;
using Microsoft.Extensions.Logging;
using System.Transactions;

namespace DongFangGuoKai.WMSPlatform.Service.InboundOrderDetail
{
    public partial class TReceivingOrderDetailService : ITReceivingOrderDetailService
    {
        #region 注入
        private readonly IRepository<TReceivingBill> receivingbillrepost;
        private readonly IRepository<TReceivingBillDetail> receivingbillDteailrepost;
        private readonly IRepository<TReceivingOrderDetail> receivingOrderDetailrepost;
        private readonly IRepository<TCell> cellrepost;
        private readonly IRepository<TMaterialKey> materialkeyrepost;
        private readonly IRepository<TStackingStorage> tStackingStorageServicerepost;
        private readonly IRepository<TInventory> inventoryrepost;
        private readonly IRepository<TInventoryDetail> inventorydetailrepost;
        private readonly IRepository<TPutawayOrder> putawayorderrepost;
        private readonly IRepository<TInstruct> instructrepost;
        private readonly IRepository<TPutawayOrderDetail> putawayorderdetailrepost;
        private readonly IRepository<TInventoryLog> inventorylogrepost;
        private readonly IAGVService aGVService;
        private readonly IRepository<TPallet> palletrepost;
        private readonly IRepository<SpreadWalls> spreadwallsrepost;
        private readonly IElectronicTSpreadWallsagsService electronicTSpreadWallsags;
        private readonly IRepository<UserColor> usercolorrepost;
        private readonly IRepository<FullBoxRecord> fullboxrecordrepsot;
        private readonly ILIMSService limsService;
        private readonly ILogger<TReceivingOrderDetailService> receivingservicelogger;

        public TReceivingOrderDetailService( 
            IRepository<TReceivingBill> receivingbillrepost,
            IRepository<TReceivingBillDetail> receivingbillDteailrepost,
            IRepository<TReceivingOrderDetail> receivingOrderDetailrepost, 
            IRepository<TCell> cellrepost,
            IRepository<TMaterialKey> materialkeyrepost,
            IRepository<TStackingStorage> tStackingStorageServicerepost,
            IRepository<TInventory> inventoryrepost,
            IRepository<TInventoryDetail> inventorydetailrepost,
            IRepository<TPutawayOrder> putawayorderrepost,
            IRepository<TInstruct> instructrepost,
            IRepository<TPutawayOrderDetail> putawayorderdetailrepost,
            IRepository<TInventoryLog> inventorylogrepost,
            IAGVService aGVService,IRepository<TPallet> palletrepost,
            IRepository<SpreadWalls> spreadwallsrepost,
            IElectronicTSpreadWallsagsService electronicTSpreadWallsags,
            IRepository<UserColor> usercolorrepost,
            IRepository<FullBoxRecord> fullboxrecordrepsot,
            ILIMSService limsService,
             ILogger<TReceivingOrderDetailService> receivingservicelogger
            )
        {
            this.receivingbillrepost = receivingbillrepost;
            this.receivingbillDteailrepost = receivingbillDteailrepost;
            this.receivingOrderDetailrepost = receivingOrderDetailrepost;
            this.cellrepost = cellrepost;
            this.materialkeyrepost = materialkeyrepost;
            this.tStackingStorageServicerepost = tStackingStorageServicerepost;
            this.inventoryrepost = inventoryrepost;
            this.inventorydetailrepost = inventorydetailrepost;
            this.putawayorderrepost = putawayorderrepost;
            this.instructrepost = instructrepost;
            this.putawayorderdetailrepost = putawayorderdetailrepost;
            this.inventorylogrepost = inventorylogrepost;
            this.aGVService = aGVService;
            this.palletrepost = palletrepost;
            this.spreadwallsrepost = spreadwallsrepost;
            this.electronicTSpreadWallsags = electronicTSpreadWallsags;
            this.usercolorrepost = usercolorrepost;
            this.fullboxrecordrepsot = fullboxrecordrepsot;
            this.limsService = limsService;
            this.receivingservicelogger = receivingservicelogger;
        }
        #endregion

        /// <summary>
        /// 生成入库单或委托单单号
        /// </summary>
        /// <returns></returns>
        private string GetInOrderBarCode()
        {
            DateTime currentDateTime = DateTime.Now;
            string year = currentDateTime.ToString("yyyy");
            string month = currentDateTime.ToString("MM");
            string day = currentDateTime.ToString("dd");
            string hour = currentDateTime.ToString("HH");
            string minute = currentDateTime.ToString("mm");
            string second = currentDateTime.ToString("ss");
            Random random = new Random();
            string randomNumber = random.Next(1000000, 9999999).ToString();

            return $"{year}{month}{day}{hour}{minute}{second}{randomNumber}";
        }

        /// <summary>
        /// 添加入库委托单
        /// </summary>
        /// <param name="addReceivingBilDTO"></param>
        /// <param name="Message"></param>
        /// <returns></returns>
        public bool AddOrders(AddReceivingBilDTO addReceivingBilDTO, out string Message)
        {
            Message = "";
            lock (_lockObj)
            {
                using var trans = new TransactionScope();
                try
                {
                    var rece = receivingbillrepost.Get(r => r.BillNo == addReceivingBilDTO.OrderNo);
                    if (rece != null)
                    {
                        if (!receivingbillrepost.Delete(rece))
                        {
                            trans.Dispose();
                            Message = "修改委托单失败";
                            return false;
                        }
                        var recedteaillist = receivingbillDteailrepost.GetList(rd => rd.BillNo == rece.BillNo);
                        if (recedteaillist.Count() <= 0)
                        {
                            trans.Dispose();
                            Message = "修改委托单失败";
                            return false;
                        }
                        if (!receivingbillDteailrepost.DeleteRange(recedteaillist))
                        {
                            trans.Dispose();
                            Message = "修改委托单失败";
                            return false;
                        }

                    }
                    if (addReceivingBilDTO.SampleInfo is null || addReceivingBilDTO.SampleInfo.Count <= 0)
                    {
                        trans.Dispose();
                        Message = "SampleInfo集合为空";
                        return false;
                    }
                    TReceivingBill receivingBill = new TReceivingBill();
                    receivingBill.CreateDate = DateTime.Now;
                    receivingBill.BillNo = addReceivingBilDTO.OrderNo;
                    receivingBill.Status = 0;
                    receivingBill.SampleTotalCount = addReceivingBilDTO.SampleTotalCount;
                    receivingBill.CustomerName = addReceivingBilDTO.CustomerName;
                    receivingBill.CustomerPhone = addReceivingBilDTO.CustomerPhone;
                    receivingBill.TotalQty = addReceivingBilDTO.SampleInfo.Sum(r => r.SampleNum);
                    if (receivingbillrepost.Insert(receivingBill) is null)
                    {
                        trans.Dispose();
                        Message = "添加入库委托单失败";
                        return false;
                    }
                    List<TReceivingBillDetail> receivingBillDetails = new List<TReceivingBillDetail>();
                    foreach (var item in addReceivingBilDTO.SampleInfo)
                    {
                        if (item.PositionType is null)
                        {
                            Message = "存储位置为空";
                            trans.Dispose();
                            return false;
                        }
                        TReceivingBillDetail receivingBillDetail = new TReceivingBillDetail();
                        receivingBillDetail.BillNo = addReceivingBilDTO.OrderNo;
                        receivingBillDetail.BillId = receivingBill.Id;
                        receivingBillDetail.MaterialId = item.SampleId;
                        receivingBillDetail.MaterialCode = item.SampleCode;
                        receivingBillDetail.MaterialName = item.SamplelName;
                        receivingBillDetail.Qty = item.SampleNum.GetValueOrDefault();
                        receivingBillDetail.SampleSize = item.SampleSize;
                        receivingBillDetail.SampleTypeCode = item.SampleTypeCode;
                        receivingBillDetail.SampleWeight = item.SampleWeight;
                        receivingBillDetail.Laboratory = item.Laboratory;
                        receivingBillDetail.PositionType = item.PositionType;
                        receivingBillDetail.ReceivedQty = 0;
                        receivingBillDetails.Add(receivingBillDetail);
                    }
                    if (receivingbillDteailrepost.InsertRange(receivingBillDetails) is null)
                    {
                        trans.Dispose();
                        Message = "添加入库委托单明细失败";
                        return false;
                    }
                    trans.Complete();
                    return true;
                }
                catch (Exception ex)
                {
                    trans.Dispose();
                    Message = "添加入库委托单失败：" + ex.Message;
                    return false;
                    throw;
                }
            }
        }

        /// <summary>
        /// 作废委托单
        /// </summary>
        /// <param name="OrderNo"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool VoidOrder(string OrderNo, out string errorMsg)
        {
            errorMsg = string.Empty;
            using var trans = new TransactionScope();
            try
            {
                var receivingbill = receivingbillrepost.Get(r => r.BillNo == OrderNo);
                if (receivingbill == null)
                {
                    errorMsg = "未查询到委托单";
                    return false;
                }
                if (!receivingbillrepost.Delete(receivingbill))
                {
                    errorMsg = "委托单修改失败";
                    trans.Dispose();
                    return false;
                }
                var receivingbilldteail = receivingbillDteailrepost.GetList(r=>r.BillNo == receivingbill.BillNo);
                if (receivingbilldteail is null || receivingbilldteail.Count() <= 0)
                {
                    errorMsg = "委托单明细查询失败";
                    trans.Dispose();
                    return false;
                }
                if (!receivingbillDteailrepost.DeleteRange(receivingbilldteail))
                {
                    errorMsg = "委托单作废失败";
                    trans.Dispose();
                    return false;
                }
                errorMsg = "提交成功";
                trans.Complete();
                return true;
            }
            catch (Exception ex)
            {
                errorMsg = "委托单作废失败：" + ex.Message;
                trans.Dispose();
                return false;
            }
        }

        /// <summary>
        /// 样品分实验室
        /// </summary>
        /// <param name="SampleId"></param>
        /// <param name="showColor"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool SortingLaboratory(string sampleCode, int showColor ,out string errorMsg)
        {
            errorMsg = string.Empty;
            var receivingbilldetail = receivingbillDteailrepost.Get(r => r.MaterialCode == sampleCode);
            if (receivingbilldetail == null)
            {
                errorMsg = "未查询到此样品";
                return false;
            }
            var spreadlist = spreadwallsrepost.GetList(s=> s.SeqNum == "1261703639" && s.Group == receivingbilldetail.Laboratory && s.SwitchState == 0);
            if (spreadlist is null || spreadlist.Count() <= 0)
            {
                errorMsg = "没有标签地址，等等再试";
                return false;
            }
            using var trans = new TransactionScope();
            try
            {
                bool result = false;
                TCell? cell;
                foreach (var spread in spreadlist)
                {
                    //会有多个电子标签是指向一个实验室的所以要看那个地址现在具备往上放样品的条件
                    var pall = palletrepost.Get(p => p.LocationCode == spread.CellCode && p.Status == 1);
                    if (pall is null)
                    {
                        result = false;
                        continue;
                    }
                    SuccessTagRequest successTagRequest = new SuccessTagRequest();
                    successTagRequest.nWall = spread.NWall;
                    successTagRequest.seqNum = spread.SeqNum;
                    successTagRequest.tagList = new List<Tag>()
                    {
                        new Tag()
                        {
                            showColor = showColor,
                            showData = spread.TagIndex,
                            tagIndex = spread.TagIndex
                        }

                    };
                    var res = electronicTSpreadWallsags.successTagResults(successTagRequest, out errorMsg);
                    if (res)
                    {
                        var fullboxlist = fullboxrecordrepsot.Get(f => f.Status == 2 && f.PalletBarcode == pall.PalletBarcode && f.MaterialId == receivingbilldetail.MaterialId);
                        if (fullboxlist == null)
                        {
                            FullBoxRecord fullBox = new FullBoxRecord()
                            {
                                CreateDate = DateTime.Now,
                                MaterialId = receivingbilldetail.MaterialId,
                                MaterialCode = receivingbilldetail.MaterialCode,
                                MaterialName = receivingbilldetail.MaterialName,
                                OrderNo = receivingbilldetail.BillNo,
                                PalletBarcode = pall.PalletBarcode,
                                FullStatus = 2,
                                Status = 1
                            };

                            if (fullboxrecordrepsot.Insert(fullBox) == null)
                            {
                                errorMsg = "点亮失败，记录样品信息失败," + receivingbilldetail.MaterialName;
                                trans.Dispose();
                                return false;
                            }
                        }
                        cell = cellrepost.Get(c => c.Code == spreadlist[0].CellCode);
                        if (cell == null)
                        {
                            errorMsg = "未查询到标签对应的" + spreadlist[0].CellCode + "储位";
                            return false;
                        }
                        errorMsg = "点亮成功,储位地址为：" + spread.CellCode;
                        trans.Complete();
                        return true;
                    }
                    else
                    {
                        errorMsg = "点亮失败：" + errorMsg;
                        trans.Dispose();
                        return false;
                    }
                }
                cell = cellrepost.Get(c => c.Code == spreadlist[0].CellCode);
                if (cell == null)
                {
                    errorMsg = "未查询到标签对应的" + spreadlist[0].CellCode + "储位";
                    return false;
                }
                errorMsg = "实验室对应的标签未绑定箱号，请到：" + cell.Name + "绑定箱号";
                return result;
            }
            catch (Exception ex)
            {
                errorMsg = "点亮失败：" + ex.Message;
                trans.Dispose();
                return false;
                throw;
            }
        }

       

        /// <summary>
        /// 样品分实验室满箱
        /// </summary>
        /// <param name="palletCode"></param>
        /// <returns></returns>
        public bool SortingLaboratoryFull(string palletCode, out string errorMsg)
        {
            errorMsg = string.Empty;
            var pall = palletrepost.Get(p=>p.PalletBarcode == palletCode);
            if (pall == null || pall.LocationCode == null)
            {
                errorMsg = "未查询到箱子";
                return false;
            }

            var fullboxs = fullboxrecordrepsot.GetList(f=> f.PalletBarcode == pall.PalletBarcode && f.Status == 1 && f.FullStatus == 2);
            if (fullboxs.Count() <= 0)
            {
                errorMsg = "箱子还没有分拣样品";
                return false;
            }

            if (fullboxs.GroupBy(p => p.Laboratory).Count() > 1)
            {
                errorMsg = "箱子样品中又不同的实验室无法满箱！";
                return false;
            }

            using var trans = new TransactionScope();
            foreach (var fullbox in fullboxs)
            {
                fullbox.FullStatus = 1;
                if (!fullboxrecordrepsot.Update(fullbox))
                {
                    errorMsg = "分拣样品信息修改失败";
                    trans.Dispose();
                    return false;
                }
            }

            var cell = cellrepost.Get(c=>c.Code == pall.LocationCode);
            if (cell is null)
            {
                errorMsg = "箱子所在储位未找到";
                trans.Dispose();
                return false; 
            }
            cell.Status = 1;
            cell.BusinessType = 0;
            cell.FullStatus = 0;
            cell.IsLock = false;
            if (!cellrepost.Update(cell))
            {
                errorMsg = "修改储位错误";
                trans.Dispose();
                return false;
            }
            var sprobj = spreadwallsrepost.Get(s => s.CellCode == cell.Code);
            if (sprobj == null)
            {
                errorMsg = "储位不在分播墙上";
                trans.Dispose();
                return false;
            }

            pall.LocationCode = null;
            pall.LocationName = null;
            pall.ErplocationName = null;
            
            if (!palletrepost.Update(pall))
            {
                errorMsg = "修改箱子数据失败";
                trans.Dispose();
                return false;
            }
         
            errorMsg = "成功";
            trans.Complete();
            return true;
            
        }

        #region 电子标签无箱操作

        /// <summary>
        /// 电子标签无箱操作样品分实验
        /// </summary>
        /// <param name="SampleId"></param>
        /// <param name="showColor"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool NotBoxLaboratory(string sampleCode, int showColor, out string errorMsg)
        {
            errorMsg = string.Empty;
            try
            {
                var receivingbilldetail = receivingbillDteailrepost.Get(r => r.MaterialCode == sampleCode);
                if (receivingbilldetail == null)
                {
                    errorMsg = "未查询到此样品";
                    return false;
                }
                var spread = spreadwallsrepost.Get(s => s.SeqNum == "1261703639" && s.Group == receivingbilldetail.Laboratory);
                if (spread == null)
                {
                    errorMsg = "实验室没有标签地址！";
                    return false;
                }

                SuccessTagRequest successTagRequest = new SuccessTagRequest();
                successTagRequest.nWall = spread.NWall;
                successTagRequest.seqNum = spread.SeqNum;
                successTagRequest.tagList = new List<Tag>()
                {
                    new Tag()
                    {
                        showColor = showColor,
                        showData = spread.TagIndex,
                        tagIndex = spread.TagIndex
                    }

                };
                var res = electronicTSpreadWallsags.successTagResults(successTagRequest, out errorMsg);
                if (res)
                {
                    errorMsg = "点亮成功";
                    return true;
                }
                else
                {
                    errorMsg = "点亮失败：" + errorMsg;
                    return false;
                }
            }
            catch (Exception ex)
            {
                errorMsg = "点亮失败：" + ex.Message;
                return false;
                throw;
            }
        }

        /// <summary>
        /// 电子标签无箱操作样品分实验室满箱
        /// </summary>
        /// <param name="palletCode"></param>
        /// <returns></returns>
        public bool NotBoxLaboratoryFull(string palletCode, out string errorMsg)
        {
            errorMsg = string.Empty;
            var pall = palletrepost.Get(p => p.PalletBarcode == palletCode && p.Status == 1);
            if (pall == null || pall.LocationCode == null)
            {
                errorMsg = "未查询到箱子或箱子已被禁用";
                return false;
            }

            var IsFullBox = fullboxrecordrepsot.GetList(f => f.PalletBarcode == pall.PalletBarcode && f.Status == 2 && f.FullStatus == 1);
            if (IsFullBox.Count > 0)
            {
                errorMsg = "箱子已满箱！";
                return false;
            }

            var fullboxs = fullboxrecordrepsot.GetList(f => f.PalletBarcode == pall.PalletBarcode && f.Status == 1 && f.FullStatus == 2);
            if (fullboxs.Count() <= 0)
            {
                errorMsg = "箱子还没有分拣样品";
                return false;
            }

            if (fullboxs.GroupBy(p => p.Laboratory).Count() > 1)
            {
                errorMsg = "箱子样品中有不同的实验室无法满箱！";
                return false;
            }

            using var trans = new TransactionScope();
            foreach (var fullbox in fullboxs)
            {
                fullbox.FullStatus = 1;
                fullbox.Status = 2;
                if (!fullboxrecordrepsot.Update(fullbox))
                {
                    errorMsg = "分拣样品信息修改失败";
                    trans.Dispose();
                    return false;
                }
            }

            errorMsg = "成功";
            trans.Complete();
            return true;

        }

        /// <summary>
        /// 分实验室的样品放箱子里
        /// </summary>
        /// <param name="pallCode"></param>
        /// <param name="sampleCode"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool SamplePutBox(string pallCode, string sampleCode, out string errorMsg)
        {
            errorMsg = string.Empty;
            var pall = palletrepost.Get(p => p.PalletBarcode == pallCode && p.Status == 1);
            if (pall == null)
            {
                errorMsg = pallCode + "箱子不存在或已被禁用";
                return false;
            }

            if (!string.IsNullOrEmpty(pall.LocationCode) || !string.IsNullOrEmpty(pall.LocationName))
            {
                errorMsg = pallCode + "箱子已在储位"+ pall.LocationName + "中，无法使用";
                return false;
            }

            var sampleobj = receivingbillDteailrepost.Get(r => r.MaterialCode == sampleCode);
            if (sampleobj == null)
            {
                errorMsg = sampleCode + "样品未查到";
                return false;
            }

            //查看箱子是否已被满箱
            var fullboxlist = fullboxrecordrepsot.GetList(f => f.PalletBarcode == pallCode && f.FullStatus == 1 && f.Status == 2);
            if (fullboxlist.Count() > 0)
            {
                errorMsg = pallCode + "箱号已满箱";
                return false;
            }

            //查看样品是否存在箱子里
            var sampleBox = fullboxrecordrepsot.Get(f => f.MaterialCode == sampleCode && f.Status == 1 && f.FullStatus == 2);
            if (sampleBox != null)
            {
                errorMsg = sampleCode + "样品已在" + sampleBox.PalletBarcode + "箱子中";
                return false;
            }

            var fullbox = fullboxrecordrepsot.Get(f => f.PalletBarcode == pallCode && f.FullStatus != 1 && f.Status == 1);
            if (fullbox != null)
            {
                if (fullbox.Laboratory != sampleobj.Laboratory)
                {
                    errorMsg = sampleobj.MaterialName + "样品和箱子里面的样品不是一个实验室";
                    return false;
                }
            }

            FullBoxRecord fullBox = new FullBoxRecord()
            {
                CreateDate = DateTime.Now,
                MaterialId = sampleobj.MaterialId,
                MaterialCode = sampleobj.MaterialCode,
                MaterialName = sampleobj.MaterialName,
                OrderNo = sampleobj.BillNo,
                PalletBarcode = pall.PalletBarcode,
                FullStatus = 2,
                Laboratory = sampleobj.Laboratory,
                Status = 1
            };

            if (fullboxrecordrepsot.Insert(fullBox) == null)
            {
                errorMsg = "记录样品信息失败," + sampleobj.MaterialName;
                return false;
            }
            errorMsg = "提交成功";
            return true;
        }

        /// <summary>
        /// 分实验室的样品和箱子解绑
        /// </summary>
        /// <param name="pallCode"></param>
        /// <param name="sampleCode"></param>
        /// <param name="errorMsg"></param>
        /// <returns></returns>
        public bool SampleUnbindingBox(string pallCode, string sampleCode, out string errorMsg)
        {
            errorMsg = string.Empty;
            var pall = palletrepost.Get(p => p.PalletBarcode == pallCode && p.Status == 1);
            if (pall == null)
            {
                errorMsg = pallCode + "箱子不存在或已被禁用！";
                return false;
            }

            var isFullBox = fullboxrecordrepsot.Get(f => f.PalletBarcode == pallCode && f.Status == 2 && f.FullStatus == 1);
            if (isFullBox != null)
            {
                errorMsg = pallCode + "箱子已满箱无法操作！";
                return false;
            }

            //查询样品是否在此箱子中
            var full = fullboxrecordrepsot.Get(f => f.PalletBarcode == pallCode && f.MaterialCode == sampleCode && f.Status == 1 && f.FullStatus == 2);
            if (full == null)
            {
                errorMsg = sampleCode + "未查询到样品绑定信息！";
                return false;
            }

            //解绑样品
            if (!fullboxrecordrepsot.Delete(full))
            {
                errorMsg = sampleCode + "样品解绑失败！";
                return false;
            }
            errorMsg = "解绑成功！";
            return true;
        }
        #endregion
    }
}
